global this_program_name := "EasyArrows"
global official_site := "https://gitee.com/LingMengQin/EasyArrows"
;------------------------------------------------
;⬇️
full_command_line := DllCall("GetCommandLine", "str")
if not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)")) {
    try
    {
        if A_IsCompiled
            Run '*RunAs "' A_ScriptFullPath '" /restart'
        else
            Run '*RunAs "' A_AhkPath '" /restart "' A_ScriptFullPath '"'
    }
    ExitApp
}   ;⬆️以管理员身份运行脚本，避免在以管理员运行的窗口中失效。

;==========================================================
;------------------------Initialize------------------------at the first start
global created := true
global exist := false
global userdir := EnvGet("UserProfile")
global program_data_dir := userdir '\' "EasyArrows"
global user_data_directory_path_file := program_data_dir '\' 'user_data_directory.txt'
global mode := "local mode"
CreateDirIfNotExist(dir) {
    if not DirExist(dir) {
        DirCreate dir
        return created
    } else {
        return exist
    }
}
CreateFileIfNotExist(filename, content) {
    if (!FileExist(filename)) {
        FileAppend content, filename
        return created
    } else {
        return exist
    }
}
open_program_data_dir() {
    Run 'explorer' ' ' program_data_dir
}
open_user_data_dir() {
    Run 'explorer' ' ' user_data_directory
}
open_official_site() {
    Run official_site
}
funcs_of_F12(selection) {
    if (selection == 1) {
        open_program_data_dir()
    } else if (selection == 2) {
        open_user_data_dir()
    } else {
        selectwindow := Gui(, "selectwindow")
        selectwindow.SetFont('s20')
        selectwindow.OnEvent("Escape", Close_selectwindow)
        btn_1 := selectwindow.AddButton(, 'open &program settings')
        btn_2 := selectwindow.AddButton('Default', 'open &user settings')
        btn_3 := selectwindow.AddButton(, 'open &official site')
        btn_1.OnEvent('Click', btn_1_Clicked)
        btn_2.OnEvent('Click', btn_2_Clicked)
        btn_3.OnEvent('Click', btn_3_Clicked)
        btn_1_Clicked(*) {
            open_program_data_dir()
            Close_selectwindow()
        }
        btn_2_Clicked(*) {
            open_user_data_dir()
            Close_selectwindow()
        }
        btn_3_Clicked(*) {
            open_official_site()
            Close_selectwindow()
        }
        Close_selectwindow(*) {
            selectwindow.Destroy()
        }
        selectwindow.Show()
    }
}
CreateUserDataDir(){
    CreateDirIfNotExist(user_data_directory)
    CreateFileIfNotExist(user_data_directory '\' 'trigger Shift+R hotkey to restart program to apply settings.', '')
}

if (FileExist(A_ScriptDir "\" "portable.txt")) {
    global mode := "portable mode"
    global program_data_dir := A_ScriptDir '\' "program-settings"
    global user_data_directory := A_ScriptDir '\' "user-settings"
    CreateDirIfNotExist(program_data_dir)
    CreateUserDataDir()
} else {
    global program_data_dir := userdir '\' "EasyArrows"
    global user_data_directory_path_file := program_data_dir '\' 'user_data_directory.txt'

    if (CreateDirIfNotExist(program_data_dir) == created) { ;if ture, means the program first start
        CreateFileIfNotExist(user_data_directory_path_file,
            'delete this note and put your directory to store data and settings. example: D:\EasyArrows\user-settings')
        CreateFileIfNotExist(program_data_dir '\' 'remove this folder to reset settings.', '')
        funcs_of_F12(1)
        Sleep 2000
        MsgBox 'please finish the user_data_directory.txt and restart the program.'
        ExitApp
    } else {
        try {
            user_data_directory := FileRead(user_data_directory_path_file, 'UTF-8')
            CreateUserDataDir()
        } catch Error as e {
            MsgBox "something's went wrong, did you correctly set the '" user_data_directory_path_file "' ?"
            MsgBox "program exiting, and the settings folder will be opened."
            open_program_data_dir()
            ExitApp
        }
    }
}

;==============================================================
;-----------------------------onStartup------------------------
TrayTip this_program_name " is running in " mode " in background. trigger F12 hotkey to open settings."

;========================
;----hotkeys settings----
global hotkeys_dir := user_data_directory '\' 'Hotkeys'
global hotkeys_on_or_off_filename := 'On&Off.txt'
CreateDirIfNotExist(hotkeys_dir)

global Ctrl_W_dir := hotkeys_dir '\' 'Ctrl+W'
CreateDirIfNotExist(Ctrl_W_dir)
global Ctrl_W_on_or_off_file := Ctrl_W_dir '\' hotkeys_on_or_off_filename
CreateFileIfNotExist(Ctrl_W_on_or_off_file, '0')
global is_Ctrl_W_enabled := false
if (FileRead(Ctrl_W_on_or_off_file, 'UTF-8') == '1') {
    is_Ctrl_W_enabled := true
}

global Space_dir := hotkeys_dir '\' 'Space'
CreateDirIfNotExist(Space_dir)
global Space_on_or_off_file := Space_dir '\' hotkeys_on_or_off_filename
CreateFileIfNotExist(Space_on_or_off_file, '1')
global is_Space_enabled := false
if (FileRead(Space_on_or_off_file, 'UTF-8') == '1') {
    is_Space_enabled := true
}

global Ctrl_Alt_T_dir := hotkeys_dir '\' 'Ctrl+Alt+T'
CreateDirIfNotExist(Ctrl_Alt_T_dir)
global Ctrl_Alt_T_to_run_setting_file := Ctrl_Alt_T_dir '\' 'run.txt'
CreateFileIfNotExist(Ctrl_Alt_T_to_run_setting_file, 'wt')
CreateFileIfNotExist
(
    Ctrl_Alt_T_dir '\' 'README.txt',
    'change the content of ' 'run.txt' " to change the command after triiger the hotkey.
    we recommand 'wt' or 'powershell' or 'cmd'"
)
;==================================================
;---------------------Switcher---------------------

Suspend

global isSleep := False

isMultiScreen() {
    if SysGet(80) = 1 {
        return False
    } else {
        return True
    }
}

;初始化激活指示器
global activeColor := 0x8cf287       ;浅绿色
global indicator := Gui(, "Active Status Indicator")
indicator.Opt("+AlwaysOnTop +Disabled -SysMenu +Owner -Caption")  ; +Owner避免显示任务栏按钮 -Caption隐藏标题栏 -SysMenu隐藏标题栏菜单按钮
indicator.BackColor := activeColor

SuspendIfUserAway() {
    if A_TimeIdle > 14000 {                     ;用户离开大于该时间时挂起
        Suspend_Script()
    }
}
CoordMode "Mouse"
Suspend_Script() {                                   ;切换脚本挂起状态
    Suspend
    if A_IsSuspended {
        indicator.Hide()
        SetTimer SuspendIfUserAway, 0
    } else {
        if isMultiScreen() {
            MouseGetPos &mouseX, &mouseY
            width := 12
            height := 12
            indicator.Show("NA w10 h10 x" mouseX - width / 2 + 1 "y" mouseY - 32)
        } else {
            indicator.Show("NA w200 h7 xCenter y0")
        }
        SetTimer SuspendIfUserAway, 5000
    }
}

CoordMode "ToolTip"
global capsState := GetKeyState("CapsLock", "T")
ShowCapsState() {
    screen_width := SysGet(78)
    if isMultiScreen() {
        MouseGetPos &mouseX, &mouseY
        toolTip_x := mouseX - 42
        toolTip_y := mouseY - 40
    } else {
        toolTip_x := screen_width / 2 - 50
        toolTip_y := 10
    }
    if capsState {
        ToolTip "CapsLock On", toolTip_x, toolTip_y
    } else {
        ToolTip "CapsLock Off", toolTip_x, toolTip_y
    }
    SetTimer HideToolTip, -1000
}
HideToolTip() {
    ToolTip
}

#SuspendExempt
global need_suspend := True
*Capslock:: {
    global
    Suspend_Script()
    if isSleep {
        Send "{Blind}{CapsLock Down}"
    } else {
        need_suspend := True
    }

    KeyWait "Capslock"              ;在此处设置阻塞，等待大写放开，防止连击。

    if !A_IsSuspended {
        if isSleep {
            Send "{Blind}{CapsLock Up}"
            capsState := GetKeyState("CapsLock", "T")
            ShowCapsState()
        } else {
            SetCapsLockState capsState
        }
        if need_suspend {
            Suspend_Script()
        }
    }
}

#SuspendExempt False

global sleepColor := 0x8b8b8b        ;浅灰色
global AwakingColor := 0x569954      ;深绿色
Wake_Script() {
    global
    isSleep := 0
    indicator.BackColor := activeColor
    SetCapsLockState capsState
    ShowCapsState()
    SetTimer Wake_Script, 0
}
Sleep_Script() {
    global
    isSleep := 1
    need_suspend := True
    indicator.BackColor := sleepColor
    if !GetKeyState("CapsLock", "P") {
        sleep 600
        Suspend_Script()
    }
}
*escape:: {
    global
    if isSleep {
        SetTimer Wake_Script, -2000
    } else {
        SetTimer Sleep_Script, -1000
        need_suspend := False
    }
    indicator.BackColor := AwakingColor
    KeyWait "Escape"
}

*escape Up:: {
    global
    if isSleep {
        SetTimer Wake_Script, 0
        indicator.BackColor := sleepColor
    } else {
        SetTimer Sleep_Script, 0
        indicator.BackColor := activeColor
    }
}

#HotIf !isSleep
Tab:: {
    global
    Send "{Blind}{CapsLock Down}"
    capsState := GetKeyState("CapsLock", "T")
}
Tab Up:: {
    Send "{Blind}{CapsLock Up}"
    ShowCapsState()
}
#HotIf
;=============================================================
;---------------------------Hotkeys---------------------------
#HotIf !isSleep

i::Up
k::Down
j::Left
l::Right
;⬆️-Arrowkeys-⬆️
u::Home
o::End
;⬆️-Home-End-⬆️
y::pgup
h::pgdn
;⬆️-PgUp-PgDn-⬆️
q::Volume_Down
w:: Send "{Volume_Mute}"
e::Volume_Up
1:: Send "{Media_Prev}"
2:: Send "{Media_Play_Pause}"
3:: Send "{Media_Next}"
;⬆️-MediaHotkeys-⬆️
WheelUp::Volume_Up
WheelDown::Volume_Down
MButton:: Send "{Volume_Mute}"
;⬆️-MouseHotkeys-⬆️
a:: Send "^#{Left}"
s:: Send "^#{Right}"
;⬆️-MutiDesktop-Control-⬆️

\::Delete   ;⬅️Delete the character to the right of the cursor

r:: Send "{F2}"       ;⬅️Rename

SC027:: Send "{AppsKey}"

Space:: {    ;⬅️Shut Down Menu
    if(is_Space_enabled) {
        todoFile := program_data_dir "\todo-before-shutdown.txt"
        if (FileExist(todoFile)) {
            content := FileRead(todoFile, "UTF-8")

            todo_window := Gui(, "todo-before-shutdown")
            todo_window.OnEvent("Escape", Close_todo_window)

            todo_window.Add("Text", , content)
            todo_window.Add("Text", , "------------------------------------------------------------")
            todo_window.Add("Text", , "Escape to cancel, Enter to continue.")

            Btn_Continue := todo_window.Add("Button", "Default", "Continue")
            Btn_Continue.OnEvent("Click", Btn_Continue_Click)

            todo_window.Show()
        } else {
            Call_Shutdown_Window()
        }

        Btn_Continue_Click(*) {
            todo_window.Destroy()
            Call_Shutdown_Window()
        }
        Close_todo_window(*) {
            todo_window.Destroy()
        }
        Call_Shutdown_Window() {
            try {
                WinMinimizeAll
                Sleep 26
                WinClose "Program Manager"
                Sleep 26
                WinActivate "Shut Down Windows"
            } catch {

            }
        }
    }
}

F12:: funcs_of_F12(0)

^!t:: ;⬅️open terminal
{
    Run FileRead(Ctrl_Alt_T_to_run_setting_file)
}

t:: SendText(FormatTime(A_Now, "yyyyMMddHHmmss"))        ;⬅️Send timestamp

;⬇️-Others(may be changed frequently)-⬇️

'::         ;⬅️Compile in vscode
{
    if (!GetKeyState("CapsLock", "T")) {
        Send "{F5}"
    } else {
        Send "^{F5}"
    }
}

^w::
{
    if (is_Ctrl_W_enabled) {
        WinClose "A"
    }
}

+r:: Reload

#HotIf
;============================================================
;------------------------MouseControl------------------------
#HotIf !isSleep

MoveMouse(direction, speed) {
    if direction == "up" {
        MouseMove 0, -speed, 0, "R"
    } else if direction == "down" {
        MouseMove 0, speed, 0, "R"
    } else if direction == "left" {
        MouseMove -speed, 0, 0, "R"
    } else if direction == "right" {
        MouseMove speed, 0, 0, "R"
    }
}
MouseControl(direction, speedctrl := 0) {
    static speed := 10
    static _direction := ""
    if direction != "space" && direction != "" {
        _direction := direction
    }
    if GetKeyState("CapsLock", "T") {
        speed := 100
    } else {
        speed := 10
    }
    if speedctrl == 0 {
        if direction == "space" {
            MouseControl(_direction, speed * 5)
        } else {
            MoveMouse(direction, speed)
        }
    } else {
        MoveMouse(direction, speedctrl)
    }
}
Tab & i:: MouseControl("up")
Tab & k:: MouseControl("down")
Tab & j:: MouseControl("left")
Tab & l:: MouseControl("right")
Tab & Space:: MouseControl("space")
Tab & u:: Send "{LButton}"
Tab & o:: Send "{RButton}"
Tab & y:: Send "{WheelUp}"
Tab & h:: Send "{WheelDown}"

#HotIf
;============================================================
;----------------------recycle bin---------------------------
;userdir := EnvGet("UserProfile")
;data_dir_name := "EasyArrows-Data-8a3d4e"

; if (FileExist(redirect_data_dir_file_path)) {
;     redirect_dir := FileRead(redirect_data_dir_file_path ,"UTF-8")
;     program_data_dir := redirect_dir "\" data_dir_name
;     CreateDirIfNotExist(program_data_dir)
; }
